package com.si3.jpa;

import java.io.File;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution.  Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateFactory {

/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal threadLocal = new ThreadLocal();
private  static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;

private HibernateFactory() {
}


static {
    try {
        // Create the SessionFactory from hibernate.cfg.xml
        sessionFactory = new Configuration().configure(new File(configFile))
                .buildSessionFactory();
    } catch (Throwable ex) {
        // Make sure you log the exception, as it might be swallowed
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

/**
* Returns the ThreadLocal Session instance.  Lazy initialize
* the SessionFactory if needed.
*
*  @return Session
*  @throws HibernateException
*/
public static Session getSession() throws HibernateException {
   Session session = (Session) threadLocal.get();

   if (session == null || !session.isOpen()) {
       System.out.println("<<<<<<<<<>>>>>>>");
       if (sessionFactory == null) {
           rebuildSessionFactory();
       }
       session = (sessionFactory != null) ? sessionFactory.openSession()
               : null;
       threadLocal.set(session);
   }

   return session;
}

/**
*  Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
   try {
       configuration.configure(configFile);
       sessionFactory = configuration.buildSessionFactory();
   } catch (Exception e) {
       System.err
               .println("%%%% Error Creating SessionFactory %%%%");
       e.printStackTrace();
   }
}

/**
*  Close the single hibernate session instance.
*
*  @throws HibernateException
*/
public static void closeSession() throws HibernateException {
   Session session = (Session) threadLocal.get();
   threadLocal.set(null);

   if (session != null) {
       session.close();
   }
}

/**
*  return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
   return sessionFactory;
}

/**
*  return session factory
*
*    session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
   HibernateFactory.configFile = configFile;
   sessionFactory = null;
}

/**
*  return hibernate configuration
*
*/
public static Configuration getConfiguration() {
   return configuration;
}

}